我們在環境中判斷物件是否碰撞的時候都會使用到碰撞器(Collider)與剛體(Rigidbody),畢竟剛體可以使物件在環境中在物理影響下移動。碰撞體必須要加上剛體才能讓雙方產生碰撞。具有剛體 Rigidbody 才能產生物理的效應。但這邊我因為不熟悉 Collision 與 Rigidbody 之間的關係,希望透過這個文章來更加理解該使用的方式。
產生碰撞的必要條件是兩個都要有 Collider,但雙方Component 中必須要有一個包含Rigidbody。在今天的實驗我們會說明,OnCollisionEnter, OnCollisionExit, OnCollisionStay 三者的差異,以及 OnTriggerEnter, OnTriggerExit, OnTriggerStay三者的差異。
先建置該兩個物件,我這邊新增一個 UpObj 也就是上面的圓球,下面 DownObj 下面是藍色的長方形方塊。
接下來是各個宣告 Collider 的新增。UpObj 包含 Rigidbody, Sphere Collider。 DownObj 僅包含 Box Collider。請記住兩個Rigidbody 內 IsTrigger 都不要勾選。
這邊補充如果點選 Collider 中的 Edit Collider,可以在Scene中有效的調整該 Collider 的大小。更加的方便微調該Collider 大小
新增一個文本到 UpObj ,取名為CollisionManagement.cs,主要是要偵測其他物件的 Trigger 與 Collision ,對自己的Collision, Trigger 是沒有反應的。就是說若你要觸發別人的Collision 或 Trigger 就需要將文本放進主要移動的物件上。
我們這邊撰寫一個程式碼針對該三者的差異,針對在不同的狀態下讓接觸圓球去顯示不同的顏色。這邊在剛接觸(Enter)的時候仍為紅色,貼著方塊移動時為藍色同時轉動該下方的方塊旋轉,離開方塊表面後圓球變成綠色。
OnCollisionEnter 當物件接觸表面時
private void OnCollisionEnter(Collision collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Collision Enter!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.red);
}
}
private void OnCollisionExit(Collision collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Collision Exit!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.green);
}
}
private void OnCollisionStay(Collision collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Collision Stay");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.blue);
collision.transform.localEulerAngles += new Vector3(0, 0, -10) * Time.deltaTime;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CollisionManagement : MonoBehaviour
{
private void OnCollisionEnter(Collision collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Collision Enter!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.red);
}
}
private void OnCollisionExit(Collision collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Collision Exit!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.green);
}
}
private void OnCollisionStay(Collision collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Collision Stay");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.blue);
collision.transform.localEulerAngles += new Vector3(0, 0, -10) * Time.deltaTime;
}
}
}
當物體掉落下的時候為紅色,瞬間接觸(OnCollisionEnter)的時候也會是紅色。
接觸貼合的時候為藍色 OnCollisionStay
離開表面的時候就會變成綠色 OnCollisionExit
首先我們點選該其中一個物件上的 IsTrigger,兩個勾選也不要緊。在這我僅勾選 UpObj 上的 IsTrigger,Sphere Collider內部的 Is Trigger 。
當 IsTrigger 點選後就會讓兩個物件無法產生碰撞的物理行為。兩物件接觸不會像剛剛一樣會接觸產生物理的反應,而是會穿透。我們可以想像IsTrigger 就僅是知道兩物件是否接觸,但互相不會有碰撞的影響。如下這裡UpObj 穿透 DownObj。
這邊我們撰寫程式,如下
private void OnTriggerEnter(Collider collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Trigger Enter!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.red);
}
}
private void OnTriggerExit(Collider collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Trigger Exit!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.green);
}
}
private void OnTriggerStay(Collider collision)
{
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Trigger Stay!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.blue);
}
}
private void OnTriggerEnter(Collider collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Trigger Enter!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.red);
}
}
private void OnTriggerExit(Collider collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Trigger Exit!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.green);
}
}
private void OnTriggerStay(Collider collision)
{
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Trigger Stay!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.blue);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CollisionManagement : MonoBehaviour
{
private void OnCollisionEnter(Collision collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Collision Enter!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.red);
}
}
private void OnCollisionExit(Collision collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Collision Exit!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.green);
}
}
private void OnCollisionStay(Collision collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Collision Stay!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.blue);
collision.transform.localEulerAngles += new Vector3(0, 0, -10) * Time.deltaTime;
}
}
private void OnTriggerEnter(Collider collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Trigger Enter!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.red);
}
}
private void OnTriggerExit(Collider collision) {
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Trigger Exit!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.green);
}
}
private void OnTriggerStay(Collider collision)
{
if(collision.gameObject.name == "DownObj")
{
Debug.Log("Trigger Stay!");
gameObject.GetComponent<Renderer>().material.SetColor("_Color", Color.blue);
}
}
}
回到 Unity 後我們調整一下該 Rigidbody 上的 Drag ,調整為 3,讓他掉下來慢一點我們好觀察該改變的狀態。
執行後結果如下
一開始圓球仍是紅色的
接下來穿透時會變成藍色的
離開被穿透的物件後
結果從 Console可以看出該三個狀態